A multithreaded programming environment allows programmers to request execution of multiple threads at the same time. However, multithreaded programs must manage contention for data between threads which may result in severe performance penalties. Multithreaded systems must allow context switching between threads and support mutual exclusion. When the performance penalty of a multithreaded environment is deemed too severe, users often give up the flexibility of multithreading and run programs non-threaded.
One common solution to the performance penalty problem in multithreaded systems is to have two versions of the program. One version of the program is designed to run threaded and one version of the program is designed to run non-threaded. This technique has the drawback that separate versions of the source code must be maintained and tested.
Another common solution uses a conditional compilation feature of a preprocessor to compile the same source files to produce different binaries for threaded and non-threaded execution. The thread management code is then ignored when compiling the non-threaded case. However, conditionally compiled code is extremely difficult to debug and test.
A third solution is to use a single source and simply test at run time whether threading is desired. This has the disadvantages that (1) it is generally still necessary to link with the thread library, causing a potentially large growth in size, (2) some thread packages impose a performance penalty for their own bookkeeping, etc., merely by being loaded, and (3) there is a performance cost for checking whether to run in a threaded or non-threaded mode.
When code is written for a threaded environment, the programmer generally needs to be aware of which threading package they are writing for. Thread package interfaces differ greatly from platform to platform making portability of code difficult.
The problem with different thread package interfaces is generally ignored. Code is typically written for a single platform and therefore a single thread package. If portability is desired, separate source or conditional compilation models as described above are generally used. Separate source or conditional compilation code has the disadvantages of maintaining and supporting multiple versions of similar code and increases debug and testing complexity.
Accordingly, a need remains for code that operates efficiently in both a multithreaded and a non-threaded environment without significantly increasing code complexity or decreasing performance.